{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "source": [
    "### Numpy 科学计算的基础软件包\n",
    "```text\n",
    "python 自带列表存储元素地址, 数值运算浪费内存和cpu, numpy可以弥补不足\n",
    "numpy 两种数组, 向量和矩阵\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-14T10:31:01.380809100Z",
     "start_time": "2024-11-14T10:31:01.365182400Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1, 3, 5, 88], [4, 6, 9, 77], [7, 8, 2, 66]]\n",
      "[1. 2. 4.]\n",
      "[1.+0.j 5.+0.j 0.+0.j]\n",
      "complex64\n",
      "3\n",
      "12\n",
      "(3, 4)\n",
      "[[ 1  3  5]\n",
      " [88  4  6]\n",
      " [ 9 77  7]\n",
      " [ 8  2 66]]\n",
      "[[ 1  3  5 88  4  6]\n",
      " [ 9 77  7  8  2 66]]\n",
      "2732613742448 2732657821232\n",
      "[[  1   3 100 100   4   6]\n",
      " [  9  77   7   8   2  66]]\n",
      "[[  1   3]\n",
      " [100 100]\n",
      " [  4   6]\n",
      " [  9  77]\n",
      " [  7   8]\n",
      " [  2  66]]\n"
     ]
    }
   ],
   "source": [
    "# 从python列表创建np.array, 形状, 大小, 元素类型\n",
    "import numpy as np\n",
    "\n",
    "np.array([1,2,5,8])  # 一维数组\n",
    "a = np.array([[1,3,5,88], [4,6,9,77], [7,8,2,66]])  # 二维数组, 矩阵\n",
    "print(a.tolist())  # 数组转列表\n",
    "\n",
    "b = np.array([1,5,0], dtype=np.complex64)  # 使用其他确定长度或格式的数据类型\n",
    "print(np.array([1,2,4], dtype=np.float16))\n",
    "print(b)\n",
    "print(b.dtype)  # 元素数据类型\n",
    "\n",
    "print(len(a))  # 一维上的元素个数\n",
    "print(a.size)  # 元素总个数\n",
    "\n",
    "print(a.shape)  # 矩阵维度属性\n",
    "a.shape = 4,3  # 按数组顺序重新组织矩阵形状\n",
    "print(a)\n",
    "a.shape = 2,-1  # -1表自动跟句元素个数推断\n",
    "print(a)\n",
    "b = a.reshape((6,2))  # 使用同一内存存数据\n",
    "b[1] = 100\n",
    "print(id(a), id(b))\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### numpy 提供性能更优的数组创建方式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2024-11-14T10:23:11.644607700Z",
     "start_time": "2024-11-14T10:23:11.628984800Z"
    },
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. , 5.5, 6. ,\n",
       "       6.5])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.arange(0, 7, 0.5)  # 左闭右开范围内按步进创建array"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int8)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linspace(1, 9, 9, dtype=np.int8)  # 创建等差数列: 包含起止, 指定数组size, 自动计算步进(等差) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  10.        ,   46.41588834,  215.443469  , 1000.        ])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.logspace(1, 3, 4)  # 创建等比数列, 起止是以10为底数的1,3次方, 指定数组size, 自动计算等比"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 0],\n",
       "       [0, 0],\n",
       "       [0, 0],\n",
       "       [0, 0],\n",
       "       [0, 0],\n",
       "       [0, 0]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros(4)  # 创建size个都是0的数组\n",
    "np.zeros((2, 3))  # tuple 参数表示创建数组的形状\n",
    "np.zeros_like(b) # 基于参数array的形状和数据类型来创建数组, 其他 xx_like 函数同理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 1., 1.])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ones(3)  # 创建size个都是1的数组, ones_like(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([8, 8, 8, 8, 8, 8])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.repeat(8, 6)  # 创建数组中, 对预设值重复size次"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[9, 9],\n",
       "       [9, 9],\n",
       "       [9, 9]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.full((3, 2), 9)  # 创建shape数组都填充预设值val"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 0, 0, 0, 0, 0],\n",
       "       [0, 1, 0, 0, 0, 0],\n",
       "       [0, 0, 1, 0, 0, 0],\n",
       "       [0, 0, 0, 1, 0, 0],\n",
       "       [0, 0, 0, 0, 1, 0],\n",
       "       [0, 0, 0, 0, 0, 1]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.eye(6, dtype=np.int_)  # 创建对角线上都是1的单位矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.70288312, 0.39170628, 0.45578772, 0.39375623, 0.14402807])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rd = np.random\n",
    "rd.rand(5)  # 0-1中均匀分布的随机值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.33920974, -1.1636117 , -0.5139719 ,  0.78078888,  0.86997359],\n",
       "       [-0.575766  , -2.15659513, -0.74521092,  0.88730592,  1.66119209],\n",
       "       [-0.25709478,  1.76744018, -0.21798334,  0.9671068 ,  0.01640286]])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rd.randn(20)  # (0为中心的)标准正态分布或高斯分布产生的样本, 参数为shape\n",
    "rd.randn(3, 5)  # 正态分布样本构成二维数组\n",
    "#help(rd.randn)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7, 8, 6])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rd.randint(5, 10)  # [5, 10) 中生成一个随机整数\n",
    "rd.randint(5, 10, 3)  # [5, 10) 中生成3个随机整数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[12 29  9  5 22 20]\n",
      " [26 22 11  9  5 21]\n",
      " [ 2 17 27 26 28  3]\n",
      " [28 12 27 18 28 12]\n",
      " [12  4 28  4 14 17]]\n"
     ]
    }
   ],
   "source": [
    "a = rd.randint(30, high=None, size=(5,6))  # [0,30) 中随机数创建size形状的数组\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# help(rd.randint)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 数组操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "22"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[0, 2]  # 元组坐标访问\n",
    "a[(1, 1)] # 元组坐标访问"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 5, 22, 20],\n",
       "       [ 9,  5, 21]])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[:2, 3:]  # 子数组, 每个维度的范围起止, 左开右闭"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[26, 11,  5],\n",
       "       [ 2, 27, 28]])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[1:3, [0, 2, 4]]  # 子数组, 前面所有维度取范围, 最后一个维度取索引列表或范围"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[11, 21]])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a[3][2]  # 链式坐标访问, a[x][y] 更多用于访问x索引限制下符合y条件的子数组\n",
    "a[:, [2,5]][a[:, 4] < 8]  # 子数组, 一维上用:取所有, 二维上取索引为[2,5]的值, 要求在所有一维数组上, 第二维上索引为4的值<8"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 4], dtype=int64),\n",
       " array([1, 4, 0, 1, 2, 3, 4, 0, 2, 4, 2], dtype=int64))"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.where(a > 21)\n",
    "# 查找a中>21的值, 返回一个原数组维度数的元组(x,y,z ...), 此处元组含2个元素\n",
    "# 每个元组长度相同, 为条件命中数据个数, (x1, y1), (x2, y2)才是实际命中数据的坐标"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3 1 2 5]\n",
      "[1. 2. 3. 1. 2. 5.]\n"
     ]
    }
   ],
   "source": [
    "s1 = np.array([1, 2, 3, 1, 2, 5], dtype=int)\n",
    "s2 = s1.astype(float)  # 自动将Python基本数据类型映射到numpy的dtype\n",
    "print(s1)\n",
    "print(s2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[4, 4, 4, 4, 4, 4, 4],\n",
       "       [4, 4, 4, 4, 4, 4, 4],\n",
       "       [2, 2, 2, 2, 2, 2, 2],\n",
       "       [2, 2, 2, 2, 2, 2, 2],\n",
       "       [2, 2, 2, 2, 2, 2, 2],\n",
       "       [2, 2, 2, 2, 2, 2, 2]])"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s1 = np.full((2, 2), 5)\n",
    "s2 = np.full((2, 7), 4)\n",
    "s3 = np.full((4, 7), 2)\n",
    "np.hstack((s1, s2))  # 水平拼接要求第1维长度相同, np.concatenate((a,b), axis=1)\n",
    "np.vstack((s2, s3))  # 垂直拼接要求第2维长度相同, np.concatenate((a,b), axis=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[array([[5],\n",
       "        [5]]),\n",
       " array([[5],\n",
       "        [5]])]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.vsplit(s3, 2)  #垂直方向上v等分\n",
    "np.hsplit(s1, 2)  # 水平方向上v等分, np.split(arr, axis=1)\n",
    "# 无法等分时会报错"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[False, False, False, False],\n",
       "       [ True,  True, False, False]])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[1, 2, 3, 4], [np.nan, np.nan, 8, 6]])\n",
    "np.isnan(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[  1.,   2.,   3.,   4.],\n",
       "       [110., 110.,   8.,   6.]])"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.nan_to_num(a, nan=110)\n",
    "# help(np.nan_to_num)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 2,  4],\n",
       "       [ 6,  8],\n",
       "       [10, 12]])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])\n",
    "np.delete(arr, 1, 0)  # 删除arr, 索引为1的行, axis=0表示删行, 1, 表示删除列, None表示删除块\n",
    "np.delete(arr, np.s_[::2], 1)  # np.s_[] 索引表达式, ::2表示取包括起止的所有行, slice step步进为2, 即从取到的第一行的索引i+2取下一行,\n",
    "#np.delete(arr, [1,2], None)  # 按照索引列表删除\n",
    "#arr[np.s_[::3]]  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1,  2,  3,  4],\n",
       "       [ 5,  6,  7,  8],\n",
       "       [ 9, 10, 11, 12]])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.view()  # 浅复制, 数据共享\n",
    "arr.copy()  # 深复制, 数据不共享"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 3,  9, 48],\n",
       "       [ 4,  6, 45],\n",
       "       [ 5,  8, 21],\n",
       "       [ 3,  7, 11]])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([[48,3,9], [4,6,45], [8,5,21], [7,3,11]])\n",
    "np.sort(arr, axis=1)  # 行内排序, 在维度索引为n的维度上排序, 产生新数组, 当维度>2 可能排序不符合预期, 建议降维到二维矩阵排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 4,  3,  9],\n",
       "       [ 7,  3, 11],\n",
       "       [ 8,  5, 21],\n",
       "       [48,  6, 45]])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.sort(axis=0)  # 列内排序, 原数组上排序\n",
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 0],\n",
       "       [0, 1, 2],\n",
       "       [1, 0, 2],\n",
       "       [1, 0, 2]], dtype=int64)"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr = np.array([[48,3,9], [4,6,45], [8,5,21], [7,3,11]])\n",
    "np.argsort(arr, axis=1)  # 行排后的原索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([48,  6, 45])"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.argmax(arr, axis=0)\n",
    "arr.max(0)  # min, max, sort类似使用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "npy = './np_data.npy'\n",
    "np.save(npy, arr)  # 保存数据为单个npy二进制文件"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[48,  3,  9],\n",
       "       [ 4,  6, 45],\n",
       "       [ 8,  5, 21],\n",
       "       [ 7,  3, 11]])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.load(npy)  # 从二进制文件npy中加载数据为ndarray"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [],
   "source": [
    "npz = './np_data.npz'\n",
    "np.savez(npz, arr=arr, a=a)  # 多个arr打包写入npz, 解压可得到多个npy, 可指定键名, 用于对应的npy文件名"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[48,  3,  9],\n",
       "       [ 4,  6, 45],\n",
       "       [ 8,  5, 21],\n",
       "       [ 7,  3, 11]])"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "f = np.load(npz)\n",
    "f['arr']  # 使用键访问数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [],
   "source": [
    "txt = './np_data.txt'  # csv最多能存2维数据, gz自动压缩为gzip\n",
    "np.savetxt(txt, arr, fmt='%.0f')  # ['%.0f', '%i'] 整数, '%.2f' 两位小数的浮点数, '%.2d' 两位整数, 不够前置添0\n",
    "# help(np.savetxt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[48,  3,  9],\n",
       "       [ 4,  6, 45],\n",
       "       [ 8,  5, 21],\n",
       "       [ 7,  3, 11]])"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.loadtxt(txt, dtype=int)  # 最多能读2维数据, 读gz, bz2自动解压"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [],
   "source": [
    "dt = './np_data.dat'\n",
    "arr.reshape((3,2,2)).tofile(dt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[48,  3],\n",
       "        [ 9,  4]],\n",
       "\n",
       "       [[ 6, 45],\n",
       "        [ 8,  5]],\n",
       "\n",
       "       [[21,  7],\n",
       "        [ 3, 11]]])"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.fromfile(dt, dtype=int).reshape((3,2,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[48,  3,  9],\n",
       "       [ 4,  6, 45],\n",
       "       [ 8,  5, 21],\n",
       "       [ 7,  3, 11]])"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([48,  3,  9,  4,  6, 45,  8,  5, 21,  7,  3, 11])"
      ]
     },
     "execution_count": 43,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "arr.flatten()  # 展开为一维数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([48,  3,  9,  4,  6, 45,  8,  5, 21,  7,  3, 11])"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ravel(arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 数学函数\n",
    "基本都是用 np.xxx调用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([8. , 7. , 0.2])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.fabs([-8, 7, -0.2])  # abs 绝对值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 4,  9, 16])"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# sqrt 平方根, square 平方, power 次方, log 自然对数, log10 10底对数, log2 2底对数\n",
    "np.square([2, 3, 4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([2., 4., 3.])"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.rint([2.5, 4.3, 3.2])  # 四舍五入"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0.5, 0.3, 0.2]), array([2., 4., 3.]))"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.modf([2.5, 4.3, 3.2])  # 拆分为小数部分数组, 整数部分数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.       , 0.8660254])"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# cos 余弦, cosh 双曲余弦, sin 正弦, sinh 双曲正弦, tan 正切, tanh 双曲正切\n",
    "np.sin([np.pi / 2 , np.pi / 3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1.        , 2.71828183, 7.3890561 ])"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.exp([0, 1, 2])  # 自然数指数值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1., -1., nan,  1.,  0.,  1.])"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sign([-0.2, -15, np.nan, 6, 0, 3])  # 符号函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 9,  5],\n",
       "       [88,  6]])"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[1, 5], [88, 0]])\n",
    "b = np.array([[9, 4], [77, 6]])\n",
    "np.maximum(a, b)  # 从两相同shape数组中, 每个相同位置取最大值构成新的数组, 新数组shape与两个数组相同, fmax(), fmin(), minimun()类似"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2])"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.mod([9, 8], [4, 3])  # 数组元素级取模(求余数)运算, 数组元素级(从两相同shape数组中, 每个位置两个元素计算后构成新的数组, shape与输入相同)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  8.,   8., -99.,  -5.,   7.,   2.])"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.copysign([-8, 8, 99, 5, 7, -2], [12, 0, -9, -2, np.nan, np.nan])  # copysign(x, y)将y的符号复制给x, 只有负数会将符号提取为-, 其余都是+"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 7, 9])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.unique([[5, 5],[7 ,9]])  # 去重, 多维自动打平"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([5, 7, 9]), array([0, 2, 3], dtype=int64))"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.unique([[5, 5],[7 ,9]], return_index=True)  # 同时返回第一次出现元素时的索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([5, 7, 9]), array([0, 0, 1, 2], dtype=int64))"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.unique([[5, 5],[7 ,9]], return_inverse=True)  # 同时返回使用去重后元素的索引来重建的原数组对应的索引列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "10"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ptp([-5, 5, 1, 2])  # 计算最值得差, 极差"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4.5"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = [[1, 2, 3, 4],\n",
    "    [5, 6, 7, 8]]\n",
    "np.median(a)  # 中位数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 统计函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1,  2,  6, 24])"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# sum, mean, var 方差, std 标准差, max, min, argmax 最大值的索引, argmin, cumsum累积和, cumprod 累计积\n",
    "np.cumprod([1, 2, 3, 4])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1,  3,  6, 11])"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.cumsum([1, 2, 3, 5])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 2., 3., 4.])"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.average(a, axis=0)  # 均值, axis=0 列均值, 1 行均值\n",
    "np.average(a, axis=0, weights=[1, 0])  # 权重数组长度应当为axis=0时列向量长度(1行向量长度), 即求均值的行或列对应元素个数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 梯度函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 3 5 7 9] [2. 2. 2. 2. 2.]\n"
     ]
    }
   ],
   "source": [
    "a = np.arange(1, 10, 2)\n",
    "print(a, np.gradient(a))  # 梯度计算连续点的变化率, x1, x2, x3, 中x2的梯度 = (x3 - x1) / 2, axis=0取0维梯度, 多维时计算所有维度的梯度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 4. ,  6. ,  6. ,  2. ],\n",
       "        [-2. , -2. , -2. , -3. ]],\n",
       "\n",
       "       [[ 3. ,  3.5, -1. , -2. ],\n",
       "        [-1.5, -1.5,  0. ,  1. ]],\n",
       "\n",
       "       [[ 2. ,  1. , -8. , -6. ],\n",
       "        [-1. , -1. ,  2. ,  5. ]]])"
      ]
     },
     "execution_count": 67,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([[[1,2,3,4],\n",
    "               [5,6,7,8]], \n",
    "              [[5,8,9,6],\n",
    "               [3,4,5,5]],\n",
    "              [[7,9,1,0],\n",
    "               [2,3,7,10]]])\n",
    "np.gradient(a, axis=0)  # shape=(3, 2, 4), axis=0时, 计算(0 -> x 仅第一维度坐标改变时的值来计算梯度, y, z) 4 = 5 - 1, 3 = (7 - 1) / 2, 2 = 7 - 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[[ 4.,  4.,  4.,  4.],\n",
       "        [ 4.,  4.,  4.,  4.]],\n",
       "\n",
       "       [[-2., -4., -4., -1.],\n",
       "        [-2., -4., -4., -1.]],\n",
       "\n",
       "       [[-5., -6.,  6., 10.],\n",
       "        [-5., -6.,  6., 10.]]])"
      ]
     },
     "execution_count": 68,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.gradient(a, axis=1)  # 计算(x, 0 -> y 仅第二维度坐标改变时的值来计算梯度, z) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 矩阵运算\n",
    "```\n",
    "+ - * / 为算术运算符, 使用对应位置的值做算术运算\n",
    "线性代数的矩阵运算包括: dot 点乘, trace 迹(左上到右下, 正对角线的和)...\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[10]])"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.mat([[7,9,1,0],\n",
    "             [2,3,7,10]])\n",
    "a.trace()  # 迹是线性变换中的特征值, 相似的线性变换, 迹相同, 参考 https://www.zhihu.com/tardis/zm/ans/255818053"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[109,  83],\n",
       "        [141,  66]])"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = np.mat([[6,5], [7,5], [4,3], [8,2]])\n",
    "np.dot(a, b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "矩阵乘法, 行向量n个元素 乘以 列向量n个元素, 对n个应积相加得到一个和; 结果矩阵一维size为行向量行数, 二维size为列向量列数;\n",
    "y=Ax,\n",
    "  A矩阵是矩阵变换, 类似一个f(x) 中的f函数; \n",
    "  x是被变换的点的转置, 因为点一般写成(x1, x2), 转置后就是一个列向量, 便于使用矩阵乘法规则;\n",
    "  y是x在经过A变换后的新的点;\n",
    "当x代表多个点时就是n列的矩阵;\n",
    "```\n",
    "参考 [矩阵乘法的本质](https://blog.csdn.net/june_young_fan/article/details/103345965)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-15.999999999999998"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c = [[4,3], [8,2]]\n",
    "np.linalg.det(np.mat(c))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[矩阵行列式](https://blog.csdn.net/weixin_46664967/article/details/113621821)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.matrix_rank(a)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[矩阵中最大不相关向量的个数就是秩](https://www.cnblogs.com/xiaoyh/p/12104263.html)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-0.125 ,  0.1875],\n",
       "       [ 0.5   , -0.25  ]])"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.inv(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A * A(-1) = I, A(-1) 就是A的逆矩阵, 两矩阵的点乘矩阵都是1, 参考 [矩阵的逆](https://www.shuxuele.com/algebra/matrix-inverse.html)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "EigResult(eigenvalues=array([ 8., -2.]), eigenvectors=array([[ 0.6       , -0.4472136 ],\n",
       "       [ 0.8       ,  0.89442719]]))"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.eig(c)   # eigh类似取反, 常用于对称矩阵"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[特征值和特征向量计算](https://www.cnblogs.com/Peyton-Li/p/9772281.html)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 2, -6],\n",
       "        [-1,  3]])"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.mat([[2,-1],[-6,3]]).T # 转置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.4142135623730951"
      ]
     },
     "execution_count": 82,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.sqrt(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 1,  5],\n",
       "        [ 7, -9],\n",
       "        [ 2,  3],\n",
       "        [-4,  8]])"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.mat([[1, 5], [7, -9]])\n",
    "b = np.mat([[2, 3], [-4, 8]])\n",
    "np.bmat('a,b a')\n",
    "np.bmat('a;b')  # 字符串表达式拼接矩阵, 逗号或空格列分隔符, 分号为行分隔符"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[ 2.],\n",
       "        [-1.]])"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.mat('2 3;3 5')\n",
    "B = np.mat('1 1').T\n",
    "\n",
    "# 计算 AX=B 中的X\n",
    "np.linalg.solve(A, B)  # 此例可用于求二元一次方程组"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
